"""
我要买入吃最多持有10天就平仓：用 hold_close
我不要过夜，或是过节假日  overnight_close

我要区分时间交易，确定非交易或是交易时间 open_time

我要用外部多空信号出场；-2,2 ：signal_close
我要用MA+ATR倍速止损：MA_ATR_close

我要固定止损，按策略中定义的成员数据确定止损价格   stop_close
我要固定止损，可以按一个买入价的  点数，百分比，金额只设置止损价止损  stop_close_byprice

我要移动止损，可以按点数，百分比，金额设置止损 move_stop_close
我要移动止损，按一个外部信号数的倍数移动止损 move_stop_close_bysignal
我要移动止损，按策略中定义的成员数据确定回撤点数  move_stop_close_byprice

我要按目标止损，三参目标出场
我要按目标止损，阶段目标出场
我要按目标止损，智能出场---函数目标  函数抬升留存率

形式总结 ：
1.参数五类：策略成员,ss，bar成员，百分比，点数，金额，初始化决定
2.运行参数趋同,触发模式  tick 还是bar;tick使用  高低价，bar使用每个bar的close判断
3.按价格止盈止损归类
3.1.给定止盈止损价  执行  onbar_base
3.2.给定止盈止损价  多单执行  onbar_base_buy
3.3.给定止盈止损价  空单执行  onbar_base_sell
3.4.多仓止盈执行  posbuy_stop_gain
3.5多仓止损执行 posbuy_stop_loss
3.6.空仓止盈执行 possell_stop_gain
3.7.空仓止损执行  possell_stop_loss
3.8. 执行止盈  onbar_base_stop_gain
3.9.执行止损   onbar_base_stop_loss
4.设置开仓价入口
5.策略重置——子类实现；isreset  特殊重置才关心使用；比如启动子类定义  启用重置  或子类不定义，不启动重置，isreset都不用设置为False
"""
class original_close:
    def __init__(self,argtype,name="",istick=True,stop_loss=None,stop_gain=None,atrkey=""):
        if name=="":
            self.name = type(self).__name__
        else:
            self.name = type(self).__name__+"("+str(name)+")"
        self.atrkey=atrkey
        self.onbar_h={"ss":self.onbar_ss,"bar":self.onbar_bar,"percent":self.onbar_percent,"tick":self.onbar_tick,"amount":self.onbat_amount,"atr":self.onbar_atr}
        self.onbar=self.onbar_h[argtype]
        self.open_price = None
        self.target_price=None
        self.stop_loss=stop_loss
        self.stop_gain=stop_gain
        self.istick=istick

    def reset(self):
        self.target_price = None
        self.open_price = None
    def reset_stop_loss_gain(self):
        self.stop_loss = None
        self.stop_gain = None
    def set_stop_loss_gain(self,stop_loss=None,stop_gain=None):
        self.stop_loss = stop_loss
        self.stop_gain = stop_gain
    def set_stop_loss(self,stop_loss=None):
        self.stop_loss = stop_loss
    def set_stop_gain(self,stop_gain=None):
        self.stop_gain = stop_gain
    def set_open_price(self,open_price):
        self.open_price=open_price
        self.target_price = self.open_price
    def ss_init_open_price(self,ss):
        if self.open_price is None:
            self.open_price=ss.signals_data[-1]["price"]
            self.target_price = self.open_price
    def onbar_base(self,ss,b,stop_loss,stop_gain,isreset=True):
        if ss.pos=="buy":
            return self.onbar_base_buy(ss,b,stop_loss,stop_gain,isreset)
        elif ss.pos=="sell":
            return self.onbar_base_sell(ss,b,stop_loss,stop_gain,isreset)
        return False, "", "",None,None
    def onbar_base_stop_loss(self,ss,b,stop_loss,isreset=True):
        if ss.pos=="buy":
            return self.posbuy_stop_loss(ss,b,stop_loss,isreset)
        elif ss.pos=="sell":
            return self.possell_stop_loss(ss,b,stop_loss,isreset)
        return False, "", "",None,None
    def onbar_base_stop_gain(self,ss,b,stop_gain,isreset=True):
        if ss.pos=="buy":
            return self.posbuy_stop_gain(ss,b,stop_gain,isreset)
        elif ss.pos=="sell":
            return self.possell_stop_gain(ss,b,stop_gain,isreset)
        return False, "", "",None,None
    def onbar_base_buy(self,ss,b,stop_loss,stop_gain,isreset=True):
        r=self.posbuy_stop_loss(ss, b, stop_loss,isreset)
        if r[0]:
            return r
        else:
            t2=r[4]
            r=self.posbuy_stop_gain(ss, b, stop_gain,isreset)
            rr=list(r)
            rr[4]=t2
            return rr
    def posbuy_stop_loss(self,ss,b,p0,isreset=True):
        isclose = False
        if p0   is not None:
            if self.istick:
                if b["low"] <= p0 and b["high"] >= p0:
                    price = p0
                    isclose = True
                    msg =self.name+ "触发止损价" + str(p0)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
                elif b["low"] <= p0 and b["high"] <= p0:
                    price = b["open"]
                    isclose = True
                    msg = self.name+"跳开止损价" + str(p0) + ",bopen" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            else:
                price = b["close"]
                if price <=p0:
                    isclose = True
                    msg = self.name+"触发止损价" + str(p0) + ",bclose" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            if isclose:
                order = {"obj": b["obj"], "timekey": b["timekey"], "price": price, "action": "closesell",
                         "info": msg}
                ss.signals_data.append(order)
                ss.pos = None
                if isreset:
                    self.reset()
                return True, "closesell", "stop_loss",p0,p0
            return False,"","",p0,p0
        return False, "", "",None,None
    def posbuy_stop_gain(self,ss,b,p0,isreset=True):
        if p0   is not None:
            isclose = False
            if self.istick:
                if b["low"] <= p0 and b["high"] >= p0:
                    price = p0
                    isclose = True
                    msg = self.name+ "触发止赢价" + str(p0)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
                elif b["low"] >= p0 and b["high"] >= p0:
                    price = b["open"]
                    isclose = True
                    msg = self.name+ "跳开止赢价" + str(p0) + ",bopen" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            else:
                price = b["close"]
                if price >= p0:
                    isclose = True
                    msg = self.name+ "触发止赢价" + str(p0) + ",bclose" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            if isclose:
                order = {"obj": b["obj"], "timekey": b["timekey"], "price": price, "action": "closesell",
                         "info": msg}
                ss.signals_data.append(order)
                ss.pos = None
                if isreset:
                    self.reset()
                return True, "closesell", "stop_gain",p0, p0
            return False, "", "", p0, p0
        return False, "", "",None,None
    def onbar_base_sell(self,ss,b,stop_loss,stop_gain,isreset=True):
        r=self.possell_stop_loss(ss, b, stop_loss,isreset)
        if r[0]:
            return r
        else:
            t1=r[3]
            r=self.possell_stop_gain(ss, b, stop_gain,isreset)
            rr = list(r)
            rr[3] = t1
            return rr
    def possell_stop_loss(self,ss,b,p0,isreset=True):
        isclose=False
        if p0   is not None:
            if self.istick:
                if b["low"] <= p0 and b["high"] >= p0:
                    price = p0
                    isclose = True
                    msg = self.name+"触发止损价" + str(p0)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
                elif b["low"] >= p0 and b["high"] >= p0:
                    price = b["open"]
                    isclose = True
                    msg = self.name+"跳开止损价" + str(p0) + ",bopen" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            else:
                price = b["close"]
                if price >= p0:
                    isclose = True
                    msg =self.name+ "触发止损价" + str(p0) + ",bclose" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            if isclose:
                order = {"obj": b["obj"], "timekey": b["timekey"], "price": price, "action": "closebuy",
                         "info": msg}
                ss.signals_data.append(order)
                ss.pos = None
                if isreset:
                    self.reset()
                return True, "closebuy","stop_loss",p0,p0
            return False, "", "", p0, p0
        return False, "", "",None,None
    def possell_stop_gain(self,ss,b,p0,isreset=True):
        if p0   is not None:
            isclose = False
            if self.istick:
                if b["low"]<=p0 and b["high"]>=p0:
                    price=p0
                    isclose = True
                    msg = self.name+"触发止赢价" + str(p0)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
                elif b["low"]<=p0 and b["high"]<=p0:
                    price=b["open"]
                    isclose = True
                    msg = self.name+"跳开止赢价" + str(p0) + ",bopen" + str(price)+",开仓价"+str(self.open_price)+",目标价"+str(self.target_price)+",其他"+str(self.stop_loss)
            else:
                price = b["close"]
                if price <= p0:
                    isclose = True
                    msg = self.name + "触发止赢价" + str(p0) + ",bclose" + str(price) + ",开仓价" + str(
                        self.open_price) + ",目标价" + str(self.target_price) + ",其他" + str(self.stop_loss)
            if isclose:
                order = {"obj": b["obj"], "timekey": b["timekey"], "price": price, "action": "closebuy",
                         "info": msg}
                ss.signals_data.append(order)
                ss.pos = None
                if isreset:
                    self.reset()
                return True,"closebuy", "stop_gain",p0,p0
            return False, "", "", p0, p0
        return False,"","",None,None

    def onbar_ss(self, ss, b):
        stop_loss = ss.__getattribute__(self.stop_loss)
        stop_gain = ss.__getattribute__(self.stop_gain)
        return self.onbar_base(ss, b, stop_loss, stop_gain)

    def onbar_bar(self, ss, b):
        if self.open_price is None:
            self.open_price=ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price - b[self.stop_loss]
            stop_gain = self.open_price + b[self.stop_gain]
            return self.onbar_base_buy(ss, b, stop_loss, stop_gain)
        elif ss.pos == "sell":
            stop_loss = self.open_price + b[self.stop_loss]
            stop_gain = self.open_price - b[self.stop_gain]
            return self.onbar_base_sell(ss, b, stop_loss, stop_gain)

    def onbar_percent(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price =self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price * (1 - self.stop_loss)
            stop_gain = self.open_price * (1 + self.stop_gain)
            return self.onbar_base_buy(ss, b, stop_loss, stop_gain)
        elif ss.pos == "sell":
            stop_loss = self.open_price * (1 + self.stop_loss)
            stop_gain = self.open_price * (1 - self.stop_gain)
            return self.onbar_base_sell(ss, b, stop_loss, stop_gain)

    def onbar_tick(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price - self.stop_loss
            stop_gain = self.open_price + self.stop_gain
            return self.onbar_base_buy(ss, b, stop_loss, stop_gain)
        elif ss.pos == "sell":
            stop_loss = self.open_price + self.stop_loss
            stop_gain = self.open_price - self.stop_gain
            return self.onbar_base_sell(ss, b, stop_loss, stop_gain)
    def onbar_atr(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        atr = b[self.atrkey]
        if atr:
            if ss.pos == "buy":
                stop_loss = self.open_price - self.stop_loss*atr
                stop_gain = self.open_price + self.stop_gain*atr
                return self.onbar_base_buy(ss, b, stop_loss, stop_gain)
            elif ss.pos == "sell":
                stop_loss = self.open_price + self.stop_loss*atr
                stop_gain = self.open_price - self.stop_gain*atr
                return self.onbar_base_sell(ss, b, stop_loss, stop_gain)
        return False, "", "",None,None
    def onbar_ss_stop_loss(self, ss, b):
        stop_loss = ss.__getattribute__(self.stop_loss)
        return self.onbar_base_stop_loss(ss, b, stop_loss)

    def onbar_bar_stop_loss(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price - b[self.stop_loss]
            return self.posbuy_stop_loss(ss, b, stop_loss)
        elif ss.pos == "sell":
            stop_loss = self.open_price + b[self.stop_loss]
            return self.possell_stop_loss(ss, b, stop_loss)

    def onbar_percent_stop_loss(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price * (1 - self.stop_loss)
            return self.posbuy_stop_loss(ss, b, stop_loss)
        elif ss.pos == "sell":
            stop_loss = self.open_price * (1 + self.stop_loss)
            return self.possell_stop_loss(ss, b, stop_loss)

    def onbar_tick_stop_loss(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_loss = self.open_price - self.stop_loss
            return self.posbuy_stop_loss(ss, b, stop_loss)
        elif ss.pos == "sell":
            stop_loss = self.open_price + self.stop_loss
            return self.possell_stop_loss(ss, b, stop_loss)
    def onbar_atr_stop_loss(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        atr = b[self.atrkey]
        if atr:
            if ss.pos == "buy":
                stop_loss = self.open_price - self.stop_loss*atr
                return self.posbuy_stop_loss(ss, b, stop_loss)
            elif ss.pos == "sell":
                stop_loss = self.open_price + self.stop_loss*atr
                return self.possell_stop_loss(ss, b, stop_loss)
        return False, "", "",None,None

    def onbar_ss_stop_gain(self, ss, b):
        stop_gain = ss.__getattribute__(self.stop_gain)
        return self.onbar_base_stop_gain(ss, b, stop_gain)

    def onbar_bar_stop_gain(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_gain = self.open_price + b[self.stop_gain]
            return self.posbuy_stop_gain(ss, b, stop_gain)
        elif ss.pos == "sell":
            stop_gain = self.open_price - b[self.stop_gain]
            return self.possell_stop_gain(ss, b, stop_gain)

    def onbar_percent_stop_gain(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_gain = self.open_price * (1 + self.stop_gain)
            return self.posbuy_stop_gain(ss, b, stop_gain)
        elif ss.pos == "sell":
            stop_gain = self.open_price * (1 - self.stop_gain)
            return self.possell_stop_gain(ss, b, stop_gain)

    def onbar_tick_stop_gain(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        if ss.pos == "buy":
            stop_gain = self.open_price + self.stop_gain
            return self.posbuy_stop_gain(ss, b, stop_gain)
        elif ss.pos == "sell":
            stop_gain = self.open_price - self.stop_gain
            return self.possell_stop_gain(ss, b, stop_gain)
    def onbar_tick_stop_gain(self, ss, b):
        if self.open_price   is None:
            self.open_price = ss.signals_data[-1]["price"]
            self.target_price = self.open_price
        atr=b[self.atrkey]
        if atr:
            if ss.pos == "buy":
                stop_gain = self.open_price + self.stop_gain*atr
                return self.posbuy_stop_gain(ss, b, stop_gain)
            elif ss.pos == "sell":
                stop_gain = self.open_price - self.stop_gain*atr
                return self.possell_stop_gain(ss, b, stop_gain)
        return False,"","",None,None
    def onbat_amount(self,ss,b):
        pass
    #     if self.open_price:
    #         if ss.pos == "buy":
    #             stop_loss = self.open_price - self.stop_loss
    #             stop_gain = self.open_price + self.stop_gain
    #             return self.onbar_base_buy(ss, b, stop_loss, stop_gain)
    #         elif ss.pos == "sell":
    #             stop_loss = self.open_price + self.stop_loss
    #             stop_gain = self.open_price - self.stop_gain
    #             return self.onbar_base_sell(ss, b, stop_loss, stop_gain)
    #     return False, "", ""